//-------------------------------------------------------------------
//	Copyright (c) 2012-2014 Zhirnov Andrey
//	This file is part of the "UXGEN-ES" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#pragma once

#include "Utils/Base/Common.h"
#include "Utils/Texture/Image/PixelFormat.h"

namespace Engine
{
namespace Utils
{

	//
	// Image
	//

	struct Image
	{
		friend struct ImageLoader;

	// types
	private:
		struct Mipmap
		{
			uvec3	dim;
			usize	offset;
			usize	size;
			///
			Mipmap () : offset(-1), size(0) {}
			Mipmap (const uvec3 &dim, usize offset, usize size) : dim(dim), offset(offset), size(size) {}
		};
		typedef array< Mipmap >		mipmap_array_t;


	// variables
	private:
		EPixelFormat::type	_pixelFormat;
		binary_array_t		_data;
		mipmap_array_t		_mipmaps;
		uvec3				_dim;


	// methods
	public:
		Image () : _pixelFormat(EPixelFormat::type(0))
		{}


		void AddMipmap (uint level, const uvec3 &dim, const uni_binbuffer_t &data)
		{
			if ( level >= _mipmaps.Count() )
			{
				_mipmaps.Resize( level+1 );
			}

			ASSERT( _mipmaps[level].offset == -1 and "overrided mipmap level!" );

			_mipmaps[level] = Mipmap( dim, _data.Count(), data.Count() );

			_data.Append( data );
		}


		void Clear ()
		{
			_pixelFormat	= EPixelFormat::_UNKNOWN;
			_dim			= uvec3();
			_data.ClearMem();
			_mipmaps.ClearMem();
		}


		usize GetDataSize () const
		{
			usize	res = 0;

			FOR( i, _mipmaps )
			{
				res += _mipmaps[i].size;
			}
			return res;
		}


		uint NumMipmaps () const
		{
			return _mipmaps.Count();
		}


		EPixelFormat::type	PixelFormat () const
		{
			return _pixelFormat;
		}


		uvec3 Dimension () const
		{
			return _dim;
		}


		bool HasMipmapLevel (uint level) const
		{
			return _GetMipmap( level ) != null;
		}


		uvec3 GetMipmapDim (uint level) const
		{
			Mipmap const *	mm = _GetMipmap( level );

			if ( mm == null )
				return uvec3(0);

			return mm->dim;
		}


		uni_binbuffer_t GetMipmapData (uint level) const
		{
			Mipmap const *	mm = _GetMipmap( level );

			if ( mm == null )
				return uni_binbuffer_t();

			return uni_binbuffer_t( _data.ptr() + mm->offset, mm->size );
		}


	private:
		Mipmap const *	_GetMipmap (uint level) const
		{
			if ( level >= _mipmaps.Count() )
				return null;

			return &_mipmaps[ level ];
		}
	};


}	// Utils
}	// Engine